package com.pug.gateway.utils;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import org.springframework.util.DigestUtils;

import java.util.*;

/**
 * @author RenGaoshuai
 * @date 2023/5/15 10:30
 * @description 签名工具类
 */
public class SignUtil {

    /**
     * 验签
     *
     * @param body
     * @param signKey
     * @param timestampKey
     * @param validTimes
     * @param appSecretKey
     * @return
     */
    public static Map<String, Object> validation(Map<String, Object> body, String signKey, String timestampKey, Integer validTimes, String appSecretKey) {
        // 拿出请求签名
        String sign = String.valueOf(body.get(signKey));
        body.remove(signKey);
        String appSecret = String.valueOf(body.get(appSecretKey));
        body.remove(appSecretKey);
        String sign1 = getSign(body,appSecret);


        Map<String, Object> map = new HashMap<>();
        // 校验签名
        if (!StrUtil.equals(sign1, sign)) {// APPID查询的密钥进行签名 和 用户签名进行比对
            map.put("code", 10000);
            map.put("status", false);
            map.put("message", "签名错误");
            return map;
        }
        // 校验签名是否失效
        if(body.containsKey(timestampKey)) {
            long thisTime = System.currentTimeMillis() - Long.valueOf(String.valueOf(body.get(timestampKey)));
            if (thisTime > validTimes) {// 比对时间是否失效
                map.put("code", 10000);
                map.put("status", false);
                map.put("message", "签名失效");
                return map;
            }
        }
        return null;
    }

    /**
     * 计算签名
     * @param params
     * @param appSecret
     * @return
     */
    public static String getSign(Map<String,Object> params,String appSecret) {
        // 参数进行字典排序
        String ret =  JSON.toJSONString(sortJson(params));

        // 使用md5算法加密待加密字符串即为sign
        String sign = DigestUtils.md5DigestAsHex(concatenate(ret.getBytes(),appSecret.getBytes()));
        return sign;
    }

    /**
     * 参数排序
     * @param obj
     * @return
     */
    public static Object sortJson(Object obj) {
        if (obj instanceof Map) {
            Map<String, Object> jsonMap = (Map<String, Object>) obj;
            JSONObject sortedJsonObject = new JSONObject(true);
            List<String> keys = new ArrayList<>(jsonMap.keySet());
            keys.sort(Comparator.naturalOrder());
            for (String key : keys) {
                if(key.equals("multipartFile")){
                    continue;
                }
                Object value = jsonMap.get(key);
                if (value instanceof Map || value instanceof List) {
                    value = sortJson(value);
                }
                sortedJsonObject.put(key, value);
            }
            return sortedJsonObject;
        } else if (obj instanceof List) {
            List<Object> jsonArray = (List<Object>) obj;
            JSONArray sortedJsonArray = new JSONArray();
            for (Object value : jsonArray) {
                if (value instanceof Map || value instanceof List) {
                    value = sortJson(value);
                }
                sortedJsonArray.add(value);
            }
            return sortedJsonArray;
        } else {
            return obj;
        }
    }

    /**
     * 替换
     * @param x1
     * @param x2
     * @return
     */

    public static byte[] concatenate(byte[] x1, byte[] x2)   {
        byte[] result = new byte[x1.length + x2.length];
        System.arraycopy(x1, 0, result, 0, x1.length);
        System.arraycopy(x2, 0, result, x1.length, x2.length);
        return result;
    }

}
